Profile picture

[Docker Compose] 네트워크(Network)

JaehyoJJAng2022년 04월 17일

▶︎ 디폴트 네트워크

기본적으로 Docker Compose는 하나의 디폴트 네트워크에 모든 컨테이너를 연결한다.

디폴트 네트워크의 이름은 docker-compose.yml 가 위치한 디렉토리 이름 뒤에 _default가 붙는다.

예를 들어보자면, 디렉토리 이름이 my_app라면 디폴트 네트워크 이름은 my_app_default 가 된다.

컨테이너 간 통신

디폴트 네트워크 안에서 컨테이너 간의 통신에서는 서비스의 이름이 호스트명으로 사용된다.

얘를 들어보자면, web 서비스의 컨테이너에서 db 서비스의 컨테이너를 대상으로 ping 명령어를 날릴수 있다.

$ docker-compose exec web ping db

64 bytes from 172.21.0.3: seq=0 ttl=64 time=0.221 ms
64 bytes from 172.21.0.3: seq=1 ttl=64 time=0.271 ms
64 bytes from 172.21.0.3: seq=2 ttl=64 time=0.367 ms

컨테이너 간 통신에서 주의할 점은 접속하는 위치가 디폴트 네트워크 내부냐 외부냐에 따라서 포트가 달라질 수 있다는 것이다.

예를 들자면, docker-compose.ymlweb 서비스의 ports 설정이 아래와 같다면

services:
  web:
    build: .
    ports:
      - "8001:80"

호스트 컴퓨터에서 접속할 때는 8001 포트를 사용해야 하고, 같은 디폴트 네트워크 내의 다른 컨테이너에서 접속할 때는 포트 80을 사용해야 한다


호스트 컴퓨터에서 web 서비스 컨테이너 접속

$ curl -I localhost:8001

HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: text/html; charset=utf-8
Content-Length: 480
ETag: W/"1e0-h+XZDnSzOoZPcJZ0k/AXKtDL92Y"
Date: Wed, 19 Apr 2023 05:36:19 GMT
Connection: keep-alive
Keep-Alive: timeout=5

같은 네트워크 내의 다른 컨테이너에서 web 서비스 컨테이너 접속

$ docker-compose exec db curl -I web:80

HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: text/html; charset=utf-8
Content-Length: 480
ETag: W/"1e0-h+XZDnSzOoZPcJZ0k/AXKtDL92Y"
Date: Wed, 19 Apr 2023 05:59:41 GMT
Connection: keep-alive
Keep-Alive: timeout=5

▶︎ 커스텀 네트워크 추가

디폴트 네트워크 뿐만 아니라 다른 네트워크도 필요에 따라 추가해줄 수 있다

docker-compose.ymlnetworks 항목 아래에 my_net이라는 네트워크를 추가하고, web 서비스의 networks 항목 아래에 my_net 네트워크를 추가하자.

이렇게 설정을 하게되면 db 서비스는 디폴트 네트워크에만 연결되지만, web 서비스는 디폴트 네트워크 뿐만 아니라 my_net 네트워크에도 연결되게 된다!

services:
  web:
    image: yshrim12/web:1.0
    ports:
      - "8000:80"
    networks:
      - default
      - my_net
  db:
    image: yshrim12/mysql:1.0
    env_file:
      - ".mysql.env"

networks:
  my_net:
    driver: bridge

Docker Compose로 애플리케이션을 올려보면 두 개의 네트워크가 생성되는 것을 알 수 있다!

$ docker-compose up -d

[+] Running 4/4
 ⠿ Network git_default  Created                                                                     0.0s
 ⠿ Network git_my_net   Created                                                                     0.0s
 ⠿ Container web        Started                                                                     0.4s
 ⠿ Container db         Started                                                                     0.3s
$ docker network ls | grep "my_net"

43bf22905641   git_my_net    bridge    local

my_net은 Docker Compose 내부에서 정의된 네트워크 이므로 애플리케이션을 내릴 때 디폴트 네트워크와 함께 삭제된다


▶︎ 외부 네트워크 사용 #1

Docker Compose가 제공하는 디폴트 네트워크 대신에 외부에서 미리 생성해놓은 다른 네트워크를 사용할 수도 있다

먼저 my_net 이라는 네트워크를 별도로 생성하자

$ docker network create my_net
$ docker network ls

NETWORK ID     NAME      DRIVER    SCOPE
01148fff8c35   bridge    bridge    local
0a5d707b4146   host      host      local
13431a24edc8   my_net    bridge    local
c3356923ba47   none      null      local

그 다음, docker-compose.yml 에서 default 네트워크의 name 키에 대한 값으로 위에서 생성했던 my_net 도커 네트워크를 기입하면 된다

networks:
  default:
    name: my_net

이제 Docker Compose로 애플리케이션을 올리고 my_net 네트워크의 상세 정보를 확인해보면 Container 항목에 두 개의 컨테이너가 연결된 것을 알 수가 있다.


$ docker-compose up -d
[+] Running 2/2
 ⠿ Container db   Started                                                                           0.4s
 ⠿ Container web  Started                                                                           0.5s

$ docker network inspect my_net
(...생략...)
        "Containers": {
            "434906917dbf5efac9555faab3897671b47790e5aa110995944e0f86134edd61": {
                "Name": "web",
                "EndpointID": "7f9a5f7597f30ec1dd12d732a720ea81cfb6586422db68e1013cacdbe037d953",
                "MacAddress": "02:42:ac:1c:00:03",
                "IPv4Address": "172.28.0.3/16",
                "IPv6Address": ""
            },
            "48c84ade3458f86ad2574a84d60e67a59aaa025bb42fd1df00bfe42ab923c6ac": {
                "Name": "db",
                "EndpointID": "afe11491820864394330a22c4aba175457225f43e2a1fbf888fbe3b9a72721c2",
                "MacAddress": "02:42:ac:1c:00:02",
                "IPv4Address": "172.28.0.2/16",
                "IPv6Address": ""
            }
        },
(...생략...)

▶︎ 외부 네트워크 사용 #2

이번에는 react-net 이라는 도커 네트워크를 생성하자.

$ docker network create react-net

위에서 생성한 도커 네트워크를 docker compose 내 특정 컨테이너만 소속하도록 코드를 작성해보자.

version: "3"

services:
  mongodb:
    image: mongo:latest
    networks:
      - my-react-net
  
  backend:
    image: yshrim12/backend:latest
    networks:
      - my-react-net
  
  frontend:
    image: yshrim12/frontend:latest

networks:
  my-react-net:
    name: react-net
    external: true

각 서비스에 대한 설명은 다음과 같다

  • mongodb: MongoDB 데이터베이스를 실행하는 Docker 이미지를 사용함. mongo:latest 이미지를 기반으로 하며, my-react-net 네트워크에 속하도록 지정되어 있음.

  • backend: 백엔드 서버를 실행하는 Docker 이미지를 사용함. yshrim12/backend:latest 이미지를 기반으로 하며, my-react-net 네트워크에 속하도록 지정되어 있음.

  • frontend: 프론트엔드 서버를 실행하는 Docker 이미지를 사용함. yshrim12/frontend:latest 이미지를 기반으로 하며, 명시적으로 네트워크에 속하지 않았기 때문에 기본적으로 default 네트워크에 속하게 된다.

  • 마지막으로, my-react-net이라는 Docker 네트워크를 정의한다. 이 네트워크는 react-net이라는 이름으로 생성되며, 외부 네트워크로 설정되어 있고, 이는 다른 Docker Compose 파일에서 정의된 네트워크를 재사용하기 위함이다.


‣ 네트워크 공유

기본적으로 docker의 경우 컨테이너를 구동할 때 사설 네트워크를 자동으로 만들어 각 컨테이너간 격리가 되고,
docker-compose의 경우 실행 디렉토리의 이름으로 네트워크를 만들어 docker-compose 네트워크 간 격리가 이뤄지게 된다.

여기서 알아볼 것은 docker-compose를 여러 개 사용할 때 하나의 network로 통합해 운영하는 방법에 대해서 다룰거다.

알고있듯이 위처럼 컨테이너들에 대해서 네트워크를 통합하는 것의 장점은 서비스간 서비스명(container_name)으로 통신이 가능해진다는 점이다. 호스트에서 컨테이너의 포트를 오픈해줄 필요가 없다는 뜻이기도 하다.


먼저 통합될 도커 네트워크를 생성해줘야 한다.

# docker network create bridge [네트워크 이름]
$ docker network create bridge test-network

그 후 설정은 간단하다. docker-compose 설정 맨 아래 부분에 네트워크 부분만 추가해주면 된다.

# ... [서비스 코드] ...

networks:
  default:
    external: true
    name: test-network

Loading script...